package balance

import (
	"context"
	"gorm.io/gorm"
	"simplifly-tech/consts"
	"simplifly-tech/model"
	model2 "simplifly-tech/payment/model"
	"simplifly-tech/utility/db"
	errCode "simplifly-tech/utility/errcode"
	"strconv"
)

type BalancePay struct {
	PayerOrgID uint
	PayeeOrgID uint
}

func (b *BalancePay) Pay(ctx context.Context, payData *model2.PayData) (*model2.PaymentResponse, error) {
	agencyPayer, err := new(model.Agency).GetByOrgID(ctx, b.PayerOrgID)
	if err != nil {
		return nil, errCode.NewError(errCode.ErrorNotFoundAgency, err)
	}

	var balanceChangePayer *model.AgencyBalanceChange
	balanceChangePayer.OrganizationID = b.PayerOrgID
	balanceChangePayer.BillType = consts.AgencyBillTypeRefundFlight
	balanceChangePayer.ReferenceID = payData.OrderID
	balanceChangePayer.Amount = payData.Amount.Neg()
	balanceChangePayer.Currency = payData.Currency
	balanceChangePayer.BeforeAmount = agencyPayer.Balance
	balanceChangePayer.AfterAmount = agencyPayer.Balance.Sub(payData.Amount)
	err = db.GetDb().Transaction(func(tx *gorm.DB) error {

		if err := tx.Set("gorm:query_option", "FOR UPDATE").First(agencyPayer, b.PayerOrgID).Error; err != nil {
			return err
		}
		if err := tx.Create(balanceChangePayer).Error; err != nil {
			return err
		}
		agencyPayer.Balance = balanceChangePayer.AfterAmount
		if err := tx.Updates(agencyPayer).Error; err != nil {
			return err
		}
		return nil
	})

	return &model2.PaymentResponse{
		OrderID: strconv.Itoa(int(balanceChangePayer.ID)),
	}, err
}

func (b *BalancePay) Refund(ctx context.Context, refundData *model2.RefundData) (string, error) {
	agencyPayer, err := new(model.Agency).GetByOrgID(ctx, b.PayerOrgID)
	if err != nil {
		return "", errCode.NewError(errCode.ErrorNotFoundAgency, err)
	}

	var balanceChangePayer *model.AgencyBalanceChange
	balanceChangePayer.OrganizationID = b.PayerOrgID
	balanceChangePayer.BillType = consts.AgencyBillTypeRefundFlight
	balanceChangePayer.ReferenceID = refundData.OrderID
	balanceChangePayer.Amount = refundData.Amount
	balanceChangePayer.Currency = refundData.Currency
	balanceChangePayer.BeforeAmount = agencyPayer.Balance
	balanceChangePayer.AfterAmount = agencyPayer.Balance.Add(refundData.Amount)
	err = db.GetDb().Transaction(func(tx *gorm.DB) error {
		if err := tx.Set("gorm:query_option", "FOR UPDATE").First(agencyPayer, b.PayerOrgID).Error; err != nil {
			return err
		}
		if err := tx.Create(balanceChangePayer).Error; err != nil {
			return err
		}
		agencyPayer.Balance = balanceChangePayer.AfterAmount
		if err := tx.Updates(agencyPayer).Error; err != nil {
			return err
		}
		return nil
	})

	return strconv.Itoa(int(balanceChangePayer.ID)), err
}

func (b *BalancePay) CancelPay(ctx context.Context, paymentID string) error {
	return nil
}
